package com.imooc.oauth2.server.config;

import java.util.LinkedHashMap;

import javax.annotation.Resource;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import com.imooc.commons.model.domain.SignInIdentity;
import com.imooc.oauth2.server.service.UserService;

/**
 * \* @author: bear
 * \* Date: 2021-07-11-15:02
 * \* describe:
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
	@Resource
	private AuthenticationManager authenticationManager;
	@Resource
	private UserService userService;
	@Resource
	private RedisTokenStore redisTokenStore;
	@Resource
	private ClientOAuth2DataConfiguration clientOAuth2DataConfiguration;
	@Resource
	private PasswordEncoder passwordEncoder;
	/**
	 * 配置令牌端口安全约束
	 * @param security
	 * @throws Exception
	 */
	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
		//允许访问token的公钥，默认/oauth/token_key 是受保护的
		security.tokenKeyAccess("permitAll()")
				//允许检查token的状态，默认/oauth/check_token 是受保护的
				.checkTokenAccess("permitAll()");
	}

	/**
	 * 客户端配置，配置授权模型
	 * @param clients
	 * @throws Exception
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

		clients.inMemory().withClient(clientOAuth2DataConfiguration.getClientId()) // 客户端标识 ID
				.secret(passwordEncoder.encode(clientOAuth2DataConfiguration.getSecret())) // 客户端安全码
				.authorizedGrantTypes(clientOAuth2DataConfiguration.getGrantTypes()) // 授权类型
				.accessTokenValiditySeconds(clientOAuth2DataConfiguration.getTokenValidityTime()) // token 有效期
				.refreshTokenValiditySeconds(clientOAuth2DataConfiguration.getRefreshTokenValidityTime()) // 刷新 token 的有效期
				.scopes(clientOAuth2DataConfiguration.getScopes()); // 客户端访问范围

	}

	/**
	 * 配置授权以及令牌的访问端点和令牌服务
	 *
	 * @param endpoints
	 * @throws Exception
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints.authenticationManager(authenticationManager)
				//具体登录的方法
				.userDetailsService(userService)
				//redis存储
				.tokenStore(redisTokenStore)
				// 令牌增强对象，增强返回的结果
				.tokenEnhancer((accessToken,auth2Authentication)->{
					// 获取登录用户的信息，然后设置
					SignInIdentity signInIdentity = (SignInIdentity)auth2Authentication.getPrincipal();
					LinkedHashMap<String, Object> map = new LinkedHashMap<>();
					map.put("nickname", signInIdentity.getNickname());
					map.put("avatarUrl", signInIdentity.getAvatarUrl());
					DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) accessToken;
					token.setAdditionalInformation(map);
					return token;
				});
		;
	}
}
